package com.campus.calculator;

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * @ClassName: Calculation
 * @Description: 计算器实现
 * @Author: hp
 * @Date: 2021/7/7 16:27
 * @version: 1.0
 */
public class Calculator {

    private static List<Character> OPERATION = Arrays.asList('+', '-', '*', '/');

    /**
     * 1.功能完整
     * 2.代码整洁
     * 3.测试保障
     * 4.小步提交
     *
     * 使用熟悉的语言完成一个计算器小程序的编写，输入输出使用标准控制台输入输出即可
     * 输入：一个合法的算式字符串  如：2*5+3
     * 输出：计算出算式的数学结果并以字符串形式输出到控制台  如 13
     * 备注：可以根据各自的时间进行拓展，至少支持进行四则运算，进阶版可以支持括号。
     *
     * @param args 参数
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String expression = sc.nextLine();

        // 计算百分数
        expression = calculatePercent(expression);
        // 计算括号内的表达式
        expression = calculateBrackets(expression);
        // 计算乘除
        expression = calculateMulAndDiv(expression);
        // 计算加减
        expression = calculateAddAndSub(expression);

        System.out.println(expression);
    }

    /**
     * 计算百分数
     *
     * @param expression 表达式
     * @return 计算过的表达式
     */
    private static String calculatePercent(String expression){
        for (int index = 0; index < expression.length(); index++) {
            char enumChar = expression.charAt(index);
            if (enumChar == '%') {
                expression = getExpressionCalculatePercent(expression,index,enumChar);
                index = 0;
            }
        }
        return expression;
    }

    /**
     * 计算括号
     *
     * @param expression 表达式
     * @return 计算过的表达式
     */
    private static String calculateBrackets(String expression){
        for (int index = 0; index < expression.length(); index++) {
            char enumChar = expression.charAt(index);
            if (enumChar == ')' || enumChar == '）') {
                expression = getExpressionCalculateBrackets(expression,index);
                index = 0;
            }
        }
        return expression;
    }

    /**
     * 计算乘和除
     *
     * @param expression 表达式
     * @return 计算过的表达式
     */
    private static String calculateMulAndDiv(String expression) {
        for (int index = 0; index < expression.length(); index++) {
            char enumChar = expression.charAt(index);
            if (enumChar == '/' || enumChar == '*') {
                expression = getExpression(expression,index,enumChar);
                index = 0;
            }
        }
        return expression;
    }

    /**
     * 计算加和减
     *
     * @param expression 表达式
     * @return 计算过的表达式
     */
    private static String calculateAddAndSub(String expression) {
        for (int index = 0; index < expression.length(); index++) {
            char enumChar = expression.charAt(index);
            if (enumChar == '+' || enumChar == '-') {
                expression = getExpression(expression,index,enumChar);
                index = 0;
            }
        }
        return expression;
    }

    /**
     * 获取下一步需要计算的表达式
     *
     * @param expression 表达式
     * @param index 下标
     * @param operation 运算符
     * @return 下一步需要计算的表达式
     */
    private static String getExpression(String expression,int index,char operation){
        StringBuffer num1 = new StringBuffer();
        StringBuffer num2 = new StringBuffer();
        for (int beg = index - 1; beg >= 0; beg--) {
            if (OPERATION.contains(expression.charAt(beg))) {
                break;
            }
            num1.append(expression.charAt(beg));
        }
        for (int beg = index + 1; beg < expression.length(); beg++) {
            if (OPERATION.contains(expression.charAt(beg))) {
                break;
            }
            num2.append(expression.charAt(beg));
        }
        String res = calculate(num1.reverse(),num2,operation);
        return expression.replace(num1.append(operation).append(num2), res);
    }

    /**
     * 获取下一步需要计算的表达式
     *
     * @param expression 表达式
     * @param index 下标
     * @param operation 运算符
     * @return 下一步需要计算的表达式
     */
    private static String getExpressionCalculatePercent(String expression,int index,char operation){
        StringBuffer num = new StringBuffer();
        for (int beg = index - 1; beg >= 0; beg--) {
            if (OPERATION.contains(expression.charAt(beg))) {
                break;
            }
            num.append(expression.charAt(beg));
        }
        String res = calculate(num.reverse(),new StringBuffer("0"),operation);
        return expression.replace(num.append(operation), res);
    }

    /**
     * 获取去掉括号后的表达式
     *
     * @param expression 表达式
     * @param index 下标
     * @return 去掉括号后的表达式
     */
    private static String getExpressionCalculateBrackets(String expression,int index){
        StringBuffer expressionBrackets = new StringBuffer();
        for (int beg = index; beg >= 0; beg--) {
            expressionBrackets.append(expression.charAt(beg));
            char enumChar = expression.charAt(beg);
            if (enumChar == '(' || enumChar == '（') {
                break;
            }
        }
        String tempExpression = String.valueOf(expressionBrackets.reverse());
        tempExpression = calculateMulAndDiv(tempExpression.substring(1,tempExpression.length()-1));
        tempExpression = calculateAddAndSub(tempExpression);

        return expression.replace(expressionBrackets,tempExpression);
    }


    /**
     * 计算
     *
     * @param num1 数1
     * @param num2 数2
     * @param operation 运算符
     * @return 计算结果
     */
    private static String calculate(StringBuffer num1, StringBuffer num2, char operation) {
        double cal1 = Double.parseDouble(num1.toString());
        double cal2 = Double.parseDouble(num2.toString());
        double res;
        switch (operation){
            case '+':{
                res = cal1 + cal2;
                break;
            }
            case '-':{
                res = cal1 - cal2;
                break;
            }
            case '*':{
                res = cal1 * cal2;
                break;
            }
            case '/':{
                res = cal1 / cal2;
                break;
            }
            case '%':{
                res = 0.01 * cal1;
                break;
            }
            default:
                res = 0;
        }
        return String.valueOf(res);
    }

}